package panda.client.ui.widgets;

import java.util.ArrayList;
import java.util.List;

import panda.client.JSNI;
import panda.client.Cardpanda;
import panda.client.engine.Observable;
import panda.client.engine.Observer;
import panda.client.enumerations.ZIndexLevel;
import panda.client.listeners.BinExplorerMouseListener;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class BinExplorer extends Composite implements Observer {
	private VerticalPanel shell = new VerticalPanel();
	private Image img = new Image(); // = new Image("card-back-clipped-50.jpg") */;
	private HorizontalPanel hp = new HorizontalPanel();
	private ListBox listBox = new ListBox(false);
	private Label dragMeTitle = new Label();
	private Bin bin;

	private boolean visible = true;

	private List<DraggableCard> cards = new ArrayList<DraggableCard>();

	public BinExplorer(final Bin bin) {
		this.bin = bin;
		bin.addObserver(this);

		hp.add(img);
		hp.add(listBox);
		hp.setSpacing(2);
		JSNI.disableSelection(img.getElement());

		listBox.setVisibleItemCount(12);

		dragMeTitle = new Label("Loading...");
		dragMeTitle.addMouseListener(new BinExplorerMouseListener(this));
		dragMeTitle.setWordWrap(false);
		DOM.setStyleAttribute(dragMeTitle.getElement(), "textAlign", "center");

		shell.add(dragMeTitle);
		shell.add(hp);

		NoteTip.setShadedStyle(dragMeTitle.getElement());

		DOM.setStyleAttribute(shell.getElement(), "border", "1px solid black");
		DOM.setStyleAttribute(shell.getElement(), "zIndex", String.valueOf(ZIndexLevel.BINEXPLORER.getZIndex()));
		initWidget(shell);
		JSNI.disableSelection(getElement());

		update(bin, null);
	}

	public String getName() {
		return bin.getName();
	}

	public boolean isEmpty() {
		return cards.isEmpty();
	}

	public String getOwnerName() {
		return bin.getOwnerName();
	}

	/**
	 * Hides or shows the binEx. Whenever we want to hide a BinEx, we need to set selectedBinEx to the appropriate hand
	 * bin.
	 */
	public void toggleVisibility() {
		if(visible) {
			hide();
			Cardpanda.clientModel.resetSelectedBinIndex();
		} else {
			show();
			// Panda.selectedBinEx = this;
			Cardpanda.clientModel.setSelectedBinEx(this);
		}

		setVisible(visible);
	}

	public void show() {
		visible = true;
		setVisible(visible);
	}

	public void hide() {
		visible = false;
		setVisible(visible);
	}

	public int getListBoxSelectedIndex() {
		return listBox.getSelectedIndex();
	}

	public DraggableCard removeSelectedCard() {
		DraggableCard removed = bin.removeCardAtIndex(listBox.getSelectedIndex());
		return removed;
	}
	
	public DraggableCard removeCardAtIndex(int index) {
		DraggableCard removed = bin.removeCardAtIndex(index);
		return removed;
	}

	public void update(Observable o, Object arg) {
		Bin observableBin = (Bin) o;

		listBox.clear();
		cards.clear();
		for(DraggableCard card : observableBin.getDraggableCardsSnapshot()) {
			listBox.addItem(card.getName());
			cards.add(card);
		}

		if(listBox.getItemCount() != 0) {
			hp.setVisible(true);

			String dragMeTitleText = bin.getOwnerAndType() + ": " + cards.size() + " cards";
			String name = Cardpanda.clientModel.getSessionID().getName();
			dragMeTitle.setText(dragMeTitleText.replace(name + "'s", "Your"));

			DeferredCommand.addCommand(new Command() {
				public void execute() {
					if(cards.size() != 0) { /* need to check again because it's a deferred command */
						/* when the client loads and reloads from the server, there's a time when bins are all empty */
						// System.out.println(cards.size());
						listBox.setSelectedIndex(cards.size() - 1);
						img.setUrl(cards.get(cards.size() - 1).getUrl50());
					}
				}
			});
		} else {
			hp.setVisible(false);

			/**
			 * This is deferred because Panda.clientModel isn't initialized during this BinEx's initialization. This
			 * BinEx's constructor is called in clientModel's constructor.
			 */
			DeferredCommand.addCommand(new Command() {
				public void execute() {
					String dragMeTitleText = bin.getOwnerAndType() + " is empty";
					String name = Cardpanda.clientModel.getSessionID().getName();
					dragMeTitle.setText(dragMeTitleText.replace(name + "'s", "Your"));
				}
			});
			// img.setUrl("card-back-clipped-50.jpg");
		}

		listBox.addChangeListener(new ChangeListener() {
			public void onChange(Widget sender) {
				int index = listBox.getSelectedIndex();
				img.setUrl(cards.get(index).getUrl50());
			}
		});
	}
}